package cn.likun.kit.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import cn.likun.kit.file.bean.FileBean;
import cn.likun.kit.file.bean.FileOrderBean;
import cn.likun.kit.file.exception.FileExistException;
import cn.likun.kit.file.support.AbstractFileFilter;
import cn.likun.kit.stream.StreamCommons;
import cn.likun.kit.validate.ValidateCommons;

/**
 * <p> 文件处理通用工具类 </p>
 */
public class FileCommons {
	
	private FileCommons() {}
	
	/**兼容 分隔符*/
	public static final String COMPAT_SEPARATOR = "/";
	
	private static final String COPY_SUFFIX = "_copy";
	/**
	 * 当前路径下的文件的改名
	 * @param filePath 文件全路径
	 * @param newName  新名称
	 * @return 
	 */
	public static boolean rename(String filePath, String newName) {
		filePath = changeSeparator(filePath);
		File file = new File(filePath);
		if (file.exists()) {
			String fileFolder = cutLastPathNode(filePath);
			file.renameTo(new File(fileFolder + File.separator + newName));
		}
		return false;
	}
	/**
	 * 创建文件夹
	 * @param dirPath
	 */
	public static boolean createFolder(String dirPath) {
		dirPath = changeSeparator(dirPath);
		File file = new File(dirPath);
		if (!file.exists() || !file.isDirectory()) {
			return file.mkdirs();
		}
		return false;
	}
	/**
	 * <p>读取文本</p>
	 * @param filePath
	 * @return
	 * @throws IOException
	 */
	public static String readFile(String filePath) throws IOException {
		filePath = changeSeparator(filePath);
		File file = new File(filePath);
		if (file.exists()) {
			FileReader reader = new FileReader(file);
			return StreamCommons.textReader(reader);
		}
		return null;
	}
	
	public static File fileBeanToFile(FileBean fileBean) {
		return new File(fileBean.getPath());
	}
	
	/**
	 * <p>创建文件</p>
	 * @param in
	 * @param filePath
	 * @throws FileExistException
	 * @throws IOException
	 */
	public static void createFile(InputStream in, String filePath) throws FileExistException, IOException {
		filePath = changeSeparator(filePath);
		File file = new File(filePath);
		if (file.exists()) {
			throw new FileExistException(filePath);
		}
		createFolder(cutLastPathNode(filePath));
		FileOutputStream out = new FileOutputStream(filePath);
		StreamCommons.binaryTransport(in, out);
	}
	/**
	 * <p>创建文件</p>
	 * @param reader
	 * @param filePath
	 * @throws IOException
	 * @throws FileExistException
	 */
	public static void createFile(Reader reader,String filePath) throws IOException, FileExistException{
		filePath = changeSeparator(filePath);
		File file = new File(filePath);
		if (file.exists()) {
			throw new FileExistException(filePath);
		}
		createFolder(cutLastPathNode(filePath));
		FileWriter writer = new FileWriter(file);
		StreamCommons.textTransport(reader, writer);
	}
	
	/**
	 * 删除文件夹
	 * @param dirPath
	 * @return
	 */
	public static void deleteFolder(String dirPath) {
		delelteFolder(dirPath, true);
	}
	/**
	 * <p>复制文件,如果文件路径相同,例如: [abc.txt-->abc_copy.txt]</p>
	 * @param filePath
	 * @param targetPath 
	 * @throws IOException
	 */
	public static void copyFile(String filePath, String targetPath) throws IOException{
		filePath = changeSeparator(filePath);
		targetPath = changeSeparator(targetPath);
		if (ValidateCommons.isNotEmpty(filePath) && ValidateCommons.isNotEmpty(targetPath)) {
			createFolder(cutLastPathNode(targetPath));
			if (filePath.equals(targetPath)) {
				targetPath = addNameSuffix(targetPath, COPY_SUFFIX);
			}
			StreamCommons.binaryTransport(new FileInputStream(filePath), new FileOutputStream(targetPath));
		}
	}
	/**
	 * <p>剪切文件</p>
	 * @param filePath 源文件全路径
	 * @param targetPath 目标文件全路径
	 * @throws IOException
	 */
	public static void cutFile(String filePath, String targetPath) throws IOException {
		copyFile(filePath, targetPath);
		deleteFile(filePath);
	}
	/**
	 * <p>为文件名添加 名称后缀 (非文件类型的后缀)</p>
	 * @param filePath
	 * @param nameSuffix
	 * @return
	 */
	public static String addNameSuffix(String filePath, String nameSuffix) {
		String folder = cutLastPathNode(filePath);
		String fileName = getLastPathNode(filePath);
		String suffix = getSuffixName(filePath);
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(folder);
		if (ValidateCommons.isEmpty(suffix)) {
			stringBuilder.append(fileName).append(fileName);
		} else {
			stringBuilder.append(fileName.substring(0, fileName.length() - suffix.length()-1)).append(nameSuffix).append(".").append(suffix);
		}
		return stringBuilder.toString();
	}
	/***
	 * <p>给文件名加前缀</p>
	 * @param filePath filePath应该是文件获取到的 , File.getPath() 取出的值
	 * @param namePreffix 名称前缀
	 * @return
	 */
	public static String addNamePreffix(String filePath, String namePreffix) {
		String fileName = getLastPathNode(filePath);
		String folder = cutLastPathNode(filePath);
		StringBuilder sb = new StringBuilder();
		sb.append(folder).append(FileCommons.COMPAT_SEPARATOR).append(namePreffix).append(fileName);
		return sb.toString();
	}
	
	/**
	 * <p>获取文件后缀名,统一小写表示</p>
	 * @param path <p>如果没有则返回  "" </p>
	 * @return
	 */
	public static String getSuffixName(String path) {
		String fileName = getLastPathNode(path);
		int beginIndex = fileName.lastIndexOf('.');
		String suffixName = "";
		if (beginIndex >-1) {
			suffixName = fileName.substring(beginIndex + 1);
		}
		return suffixName.toLowerCase();
	}
	/**
	 * <p>删除文件夹下的所有文件</p>
	 * @param folder 文件夹路径
	 * @param containFolder true ? 删除文件夹 :... ;
	 */
	public static void delelteFolder(String folder, boolean containFolder) {
		folder = changeSeparator(folder);
		File file = new File(folder);
		if (file.exists() && file.isDirectory()) {
			String[] filepaths = file.list();
			if (ValidateCommons.isEmpty(filepaths) && containFolder) {
				file.delete();
			} else {
				for (String filepath : filepaths) {
					File innerFile = new File(filepath);
					if (innerFile.isFile()) {
						innerFile.delete();
					} else {
						delelteFolder(filepath, containFolder);
					}
				}
			}
		}
	}
	/**
	 * <p>删除所有文件 </p>
	 * @param fileBeans 需要删除的[ 文件/文件夹 ]列表
	 * @param containFolder 是否删除文件夹 
	 * @return 
	 */
	public static void deleteFiles(List<FileBean> fileBeans) {
		if (ValidateCommons.isNotEmpty(fileBeans)) {
			for (FileBean fileBean : fileBeans) {
				if (fileBean.getIsFolder()) {
					delelteFolder(fileBean.getPath(), true);
				}else{
					deleteFile(fileBean);
				}
			}
		}
	}
	/**
	 * <p>删除文件</p>
	 * @param path [文件/文件夹] 路径
	 * @return [空文件夹 or 文件] ? true : false ;
	 */
	public static boolean deleteFile(String filepath) {
		filepath = changeSeparator(filepath);
		File file = new File(filepath);
		if (file.exists() && file.isFile()) {
			return file.delete();
		} else if (file.exists() && file.isDirectory()) {
			if (ValidateCommons.isEmpty(file.list())) {
				return file.delete();
			}
		}
		return false;
	}
	/**
	 * <p>删除文件</p>
	 * @param <p>fileBean [文件/文件夹]</p>
	 * @return  [空文件夹 or 文件] ? true : false ;
	 */
	public static boolean deleteFile(FileBean fileBean) {
		return deleteFile(fileBean.getPath());
	}
	
	/**
	 * 获取文件夹下面的文件
	 * @param path 如果此路径不是存在的文件夹 ,则返回一个 emptyList
	 * @param fileOdrderBean <p>排序方式  </p>
	 *  					 <p>可以根据 NAME,TYPE,SIZE,LAST_MODIFIED进行排序</p>
	 *  					 <p>isDesc 为true时 , 按照上述条件进行倒序排列</p>
	 * @param fileFilter 	 <p>文件过滤器 , 如果path存在于 fileFilter的getScopes()中 , 则进行过滤 , </p>
	 * 						 <p>抽象方法  isThrowFile(FileBean fileBean)需要用户自己实现过滤规则 , 如果返回true则表示此FileBean是一个抛弃的文件, 不会加入到返回结果List&lt;FileBean>中 </p>
	 * @return
	 */
	public static List<FileBean> listFolder(String path, FileOrderBean fileOdrderBean, AbstractFileFilter fileFilter) {
		fileOdrderBean = ValidateCommons.isEmpty(fileOdrderBean)?new FileOrderBean():fileOdrderBean;
		path = changeSeparator(path);
		boolean isThrowable =false;
		if (ValidateCommons.isNotEmpty(fileFilter)) {
			Set<String> scopes = fileFilter.getScopes();
			if (ValidateCommons.isNotEmpty(scopes)) {
				for (String scope : scopes) {
					if (path.equals(changeSeparator(scope))) {
						isThrowable = true;
						break;
					}
				}
			}
		} 
		List<FileBean> fileBeans = new ArrayList<FileBean>();
		File folder = new File(path);
		if (folder.exists() && folder.isDirectory()) {
			File[] files = folder.listFiles();
			if (ValidateCommons.isNotEmpty(files)) {
				for (File file : files) {
					FileBean fileBean = new FileBean(file);
					if (isThrowable && fileFilter.isThrowFile(fileBean)) {
						continue;
					}
					fileBeans.add(fileBean);
				}
			}
			Collections.sort(fileBeans, fileOdrderBean);
		}
		return fileBeans;
	}
	
	/**
	 * 删除文件夹下所有文件
	 * @param path
	 * @param containFolder
	 * @return
	 */
	public static boolean deleteFiles(String path ,boolean containFolder) {
		
		return false;
	}
	
	/**
	 * <p>转换为系统兼容的路径间隔符</p>
	 * @param path path
	 * @param isStandard true ? 标准化,去除最后一个分隔符 : 转换后的系统兼容路径 ;
	 * @return 
	 */
	public static String changeSeparator(String path, boolean isStandard) {
		if (ValidateCommons.isNotEmpty(path)) {
			path = new File(path).getPath();
			path.replace('\\', File.separatorChar).replace('/', File.separatorChar);
			if (isStandard) {
				if (path.endsWith(File.separator)) {
					path = path.substring(0,path.length()-1);
				}
			}
		}
		return path;
	}
	/**
	 * <p>转换为系统兼容的路径间隔符</p>
	 * @param path 
	 * @return 标准化,去除最后一个分隔符
	 */
	public static String changeSeparator(String path) {
		return changeSeparator(path, true);
	}
	/**
	 *  转换为 WEB 兼容的路径间隔符 /，并标准化路径
	 * @param path
	 * @param isStandard isStandard true ? 标准化,去除最后一个分隔符 : 转换后的系统兼容路径 ;
	 * @return 兼容(/)
	 */
	public static String changeCompatSeparator(String path, boolean isStandard) {
		if (ValidateCommons.isNotEmpty(path)) {
			path = new File(path).getPath();
			path = path.replace('\\', '/');
			if (isStandard && path.endsWith("/")) {
				path = path.substring(0, path.length()-1);
			}
		}
		return path;
	}
	/**
	 *  转换为 WEB 兼容的路径间隔符 /，并标准化路径
	 * @param path
	 * @return 标准化,去除最后一个分隔符  兼容(/)
	 */
	public static String changeCompatSeparator(String path) {
		return changeCompatSeparator(path, true);
	}
	/**
	 * 获取路径的最后一级
	 * @param path
	 * @return 最后一级文件夹或者文件名
	 */
	public static String getLastPathNode(String path) {
		path = changeSeparator(path);
		int lastNodeBegin = path.lastIndexOf(File.separator) + 1;
		return path.substring(lastNodeBegin);
	}
	/**
	 * 去除最后一级路径后, 如果路径就只有一级, 则返回 ""
	 * @param path 
	 * @return  去除最后一级路径后的路径 
	 */
	public static String cutLastPathNode(String path) {
		path = changeSeparator(path);
		String lastNode = getLastPathNode(path);
		if (path.equals(lastNode)) {
			path = "";
		} else {
			path = path.substring(0,path.length() - (lastNode.length() + 1));
		}
		return path;
	}
}
































